package Stacking;

import java.util.ArrayList;

import ClassificationAlgorithm.CollectiveClassificationAlgorithmClass;
import ClassificationAlgorithm.ContentOnlyClass;
import ClassificationAlgorithm.LinkOnlyClass;
import Definitions.GraphClass;
import Definitions.NodeClass;
import Global.ConstantVariable;
import Global.GlobalClass;
import Result.ResultClassListClass;
import Sampling.SamplingAbstractClass;
import Utility.WorkerUtilityClass;

public class StackingManagerClass {
	
	GraphClass orgGraph;
	GlobalClass orgGlobal;
	SamplingAbstractClass sampling;
	int foldNo;
	
	double[][][] probabilityDistributionMatrixOfTheClassifiersForStacking;
	ArrayList<CollectiveClassificationAlgorithmClass> classifierList;
	
	
	
	public StackingManagerClass(ArrayList<CollectiveClassificationAlgorithmClass> classifierList, GraphClass orgGraph, GlobalClass orgGlobal, SamplingAbstractClass sampling, int foldNo)
	{
		int datasetSize = orgGraph.getDataSet().size();
		this.orgGraph = orgGraph;		
		this.orgGlobal = orgGlobal;		
		this.classifierList = classifierList;
		this.sampling = sampling;
		this.foldNo = foldNo;
		probabilityDistributionMatrixOfTheClassifiersForStacking = new double[classifierList.size()][datasetSize][orgGlobal.classSize];
		
	}
	
	public ResultClassListClass testWithStacking()
	{
		ResultClassListClass resultsForSTA = null;
		ArrayList<Double> arrayListFormOfTheProbDistributions;
		
		GraphClass newGraphWhichHasPrevProbsAsContentFeatures = (GraphClass) orgGraph.clone();
		GlobalClass newGlobalForTheGraphWhichHasPrevProbsAsContentFeatures = (GlobalClass) orgGlobal.clone();
		
		CollectiveClassificationAlgorithmClass cca;
		
		ArrayList<NodeClass> nodeListInTheDataset=orgGraph.getDataSet();
		
		//Now create probability Dist. matrix for all nodes
		
 		
		int sizeOfTheClassifierList = classifierList.size();
		
		WorkerUtilityClass.initializeThreeDimensionalArray(probabilityDistributionMatrixOfTheClassifiersForStacking, 0.0);

		for(int i=0; i<sizeOfTheClassifierList;i++)
		{
			cca = classifierList.get(i);

			int testNodeNo=0;

			if(ConstantVariable.MetaClassifier_ConstantVariables.isStabilityIssueEnabledForLinkBasedFeatures==true && cca.getName()==ConstantVariable.CCA_ConstantVariables.LINK_ONLY)
			{
				LinkOnlyClass LoCCATemp;
				LoCCATemp = (LinkOnlyClass) cca;
				LoCCATemp.BecomeStableForTheTest(sampling);
			}

			for(NodeClass k : nodeListInTheDataset)
			{	
				probabilityDistributionMatrixOfTheClassifiersForStacking[i][testNodeNo] = cca.TestNodeForAlpha(k, sampling, foldNo);					
				testNodeNo++;
			}	
		}			
		
		
		for(int j=0; j<probabilityDistributionMatrixOfTheClassifiersForStacking[0].length; j++)
		{
			double[] mergedFormOfProbDistributions = probabilityDistributionMatrixOfTheClassifiersForStacking[0][j];
			
			for(int i=1; i<probabilityDistributionMatrixOfTheClassifiersForStacking.length; i++)			
			{
				mergedFormOfProbDistributions = WorkerUtilityClass.mergeTwoDoubleArrays(mergedFormOfProbDistributions, probabilityDistributionMatrixOfTheClassifiersForStacking[i][j]);				
			}
			//cls type -node no
			arrayListFormOfTheProbDistributions = WorkerUtilityClass.getArrayListFromDoubleArray(mergedFormOfProbDistributions);
			try
			{				
				newGraphWhichHasPrevProbsAsContentFeatures.getDataSet().get(j).getContentList().get(ConstantVariable.Common_ConstantVariables.DEFAULT_CONTENT_TYPE).setAttributeList(arrayListFormOfTheProbDistributions);				
			}
			catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
				System.exit(0);
			}			
		}		
		
		resultsForSTA=ContentOnlyClass.TestWithWeka(newGraphWhichHasPrevProbsAsContentFeatures, newGlobalForTheGraphWhichHasPrevProbsAsContentFeatures, 1/*ConstantVariable.CCA_ConstantVariables.NUMBER_OF_FOLDS_FOR_CONTENT_ONLY*/, sampling, ConstantVariable.ExecutionParameters.SELECTED_LOCAL_CLASSIFIER, ConstantVariable.ExecutionParameters.SELECTED_SECOND_LEVEL_LOCAL_CLASSIFIER_FOR_STACKING);
		
		return resultsForSTA;
	}
}
